home *** CD-ROM | disk | FTP | other *** search
/ Amiga Plus Special 18 / AMIGAplus Sonderheft 18 (1999)(ICP)(DE)[!].iso / PD / Anwendungen / FS1541-13 / packet.c < prev    next >
C/C++ Source or Header  |  1999-01-03  |  29KB  |  1,209 lines

  1.  
  2. /*
  3.  * FS1541 - packet processor
  4.  *
  5.  * If you are new to this subject and want to learn about it, you *must*
  6.  * have the Amiga Guru Book next to you and compare the routines for each
  7.  * packet with the specifications in the book -- then you will understand!
  8.  *
  9.  * Copyright (C) 1996 - 1998 Michael Krause
  10.  *
  11.  * This program is free software; you can redistribute it and/or modify
  12.  * it under the terms of the GNU General Public License as published by
  13.  * the Free Software Foundation; either version 2 of the License, or
  14.  * (at your option) any later version.
  15.  *
  16.  * This program is distributed in the hope that it will be useful,
  17.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  18.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  19.  * GNU General Public License for more details.
  20.  *
  21.  * You should have received a copy of the GNU General Public License
  22.  * along with this program; if not, write to the Free Software
  23.  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  24.  */
  25.  
  26. #include <string.h>
  27.  
  28. #include <exec/types.h>
  29. #include <exec/execbase.h>
  30. #include <exec/memory.h>
  31. #include <dos/dosextens.h>
  32. #include <dos/filehandler.h>
  33.  
  34. #include <proto/exec.h>
  35. #include <proto/dos.h>
  36. #include <proto/utility.h>
  37.  
  38. #include "main.h"
  39. #include "packet.h"
  40. #include "support.h"
  41. #include "volume.h"
  42. #include "disk.h"
  43.  
  44. static BOOL getfiledata(UBYTE entry, struct FHArg1 *fharg1);
  45. static BPTR trylockfile(LONG *err2, BSTR name, LONG access, struct FHArg1 *fharg1, BOOL allow_root);
  46.  
  47. static UBYTE fname1[20];
  48.  
  49. int inhibited = FALSE;
  50.  
  51. static LONG TestLock(struct FileLock *fl);
  52. static inline LONG TestLockRef(struct FileLock *fl);
  53.  
  54. static struct BAM empty_bam = {
  55.     0x12,0x01,0x41,0x00,
  56.  
  57.     {
  58.         0x15FFFF1F,0x15FFFF1F,0x15FFFF1F,
  59.         0x15FFFF1F,0x15FFFF1F,0x15FFFF1F,0x15FFFF1F,
  60.         0x15FFFF1F,0x15FFFF1F,0x15FFFF1F,0x15FFFF1F,
  61.         0x15FFFF1F,0x15FFFF1F,0x15FFFF1F,0x15FFFF1F,
  62.         0x15FFFF1F,0x15FFFF1F,0x11FCFF07,0x13FFFF07,
  63.         0x13FFFF07,0x13FFFF07,0x13FFFF07,0x13FFFF07,
  64.         0x13FFFF07,0x12FFFF03,0x12FFFF03,0x12FFFF03,
  65.         0x12FFFF03,0x12FFFF03,0x12FFFF03,0x11FFFF01,
  66.         0x11FFFF01,0x11FFFF01,0x11FFFF01,0x11FFFF01
  67.     },
  68.  
  69.     {
  70.         0x58,0x58,0x58,0x58,0x58,0x58,0x58,0x58,0x58,0x58,0x58,0x58,0x58,0x58,0x58,0x58
  71.     },
  72.  
  73.     {
  74.         0xA0,0xA0
  75.     },
  76.  
  77.     {
  78.         0x59,0x59,0xA0,0x32,0x41
  79.     },
  80.  
  81.     {
  82.         0xA0,0xA0,0xA0,0xA0,0x00,0x00,0x00,0x00,0x00,
  83.         0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
  84.         0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
  85.         0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
  86.         0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
  87.         0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
  88.     }
  89. };
  90.  
  91. /*-------------------------------------------------------------------------*/
  92.  
  93. void DoPackets(void)
  94. {
  95.     struct DosPacket *packet;
  96.  
  97.     while((packet = GetPacket(ourport)))
  98.     {
  99.         LONG error = DOSFALSE;
  100.         LONG err2 = 0;
  101.         BOOL f = TRUE;
  102.  
  103.         dpsender = packet->dp_Port;
  104.  
  105.         if(inhibited)
  106.         {
  107.             switch(packet->dp_Type)
  108.             {
  109.                 case ACTION_DISK_INFO:
  110.                 case ACTION_INHIBIT:
  111.                 case ACTION_FORMAT:
  112.                     break;
  113.  
  114.                 default:
  115.                     f = FALSE;
  116.                     err2 = ERROR_NOT_A_DOS_DISK;
  117.                     break;
  118.             }
  119.         }
  120.  
  121.         if(f) switch(packet->dp_Type)
  122.         {
  123.             case ACTION_LOCATE_OBJECT:
  124.             {
  125.                 struct FileLock *fl = BADDR(packet->dp_Arg1);
  126.                 struct FHArg1 fharg1;
  127.  
  128.                 if((err2 = TestLock(fl)))
  129.                     break;
  130.                 else if(!curvolumenode)
  131.                 {
  132.                     err2 = disk_inserted ? ERROR_NOT_A_DOS_DISK : ERROR_NO_DISK;
  133.                     break;
  134.                 }
  135.  
  136.                 /* This FileSystem is easy since we don't have to take
  137.                    care of any FileLock path tracking and resolving */
  138.  
  139.                 error = trylockfile(&err2, packet->dp_Arg2, packet->dp_Arg3, &fharg1, TRUE);
  140.                 MotorOff();
  141.                 break;
  142.             }
  143.  
  144.             case ACTION_FREE_LOCK:
  145.             {
  146.                 struct FileLock *fl = BADDR(packet->dp_Arg1);
  147.  
  148.                 if(fl)
  149.                     freelock(fl);
  150.  
  151.                 MotorOff();
  152.                 error = DOSTRUE;
  153.                 break;
  154.             }
  155.  
  156.             case ACTION_COPY_DIR:
  157.             {
  158.                 struct FileLock *fl = BADDR(packet->dp_Arg1);
  159.  
  160.                 if(fl) {
  161.                     if(fl->fl_Access == EXCLUSIVE_LOCK) {
  162.                         /* Don't duplicate exclusive locks */
  163.                         err2 = ERROR_OBJECT_IN_USE;
  164.                     }
  165.                     else {
  166.                         if(fl->fl_Volume == MKBADDR(curdoslist)) {
  167.                             /* Try to duplicate it! */
  168.                             err2 = ERROR_NO_FREE_STORE;
  169.                             error = makelock(fl->fl_Key, SHARED_LOCK);
  170.                         }
  171.                         else {
  172.                             /* The reference disk is currently not inserted. */
  173.                             err2 = ERROR_DEVICE_NOT_MOUNTED;
  174.                         }
  175.                     }
  176.                 }
  177.                 else {
  178.                     if(curvolumenode) {
  179.                         /* Return shared lock on root directory */
  180.                         err2 = ERROR_NO_FREE_STORE;
  181.                         error = makelock(0, SHARED_LOCK);
  182.                     }
  183.                     else {
  184.                         err2 = ERROR_NO_DISK;
  185.                     }
  186.                 }
  187.  
  188.                 break;
  189.             }
  190.  
  191.             case ACTION_PARENT:
  192.             {
  193.                 struct FileLock *fl = BADDR(packet->dp_Arg1);
  194.  
  195.                 if(fl) {
  196.                     if(!(err2 = TestLockRef(fl))) {
  197.                         if(fl->fl_Key != 0) {
  198.                             /* Return shared lock on root directory */
  199.                             err2 = ERROR_NO_FREE_STORE;
  200.                             error = makelock(0, SHARED_LOCK);
  201.                         }
  202.                         else {
  203.                             err2 = 0;
  204.                         }
  205.                     }
  206.                 }
  207.                 else {
  208.                     err2 = 0;
  209.                 }
  210.  
  211.                 break;
  212.             }
  213.  
  214.             case ACTION_SAME_LOCK:
  215.             {
  216.                 struct FileLock *fl1 = BADDR(packet->dp_Arg1);
  217.                 struct FileLock *fl2 = BADDR(packet->dp_Arg2);
  218.  
  219.                 err2 = 0;
  220.  
  221.                 if(fl1 == fl2 || ((fl1->fl_Volume == fl2->fl_Volume) && (fl1->fl_Key == fl2->fl_Key)))
  222.                     error = DOSTRUE;
  223.  
  224.                 break;
  225.             }
  226.  
  227.             case ACTION_EXAMINE_OBJECT:
  228.             {
  229.                 struct FileLock *fl = BADDR(packet->dp_Arg1);
  230.                 struct FileInfoBlock *fib = BADDR(packet->dp_Arg2);
  231.  
  232.                 if(fl && fl->fl_Key != 0) {
  233.                     /* Examine file */
  234.                     struct FHArg1 fharg1;
  235.                     int entry;
  236.                     int special;
  237.  
  238.                     fib->fib_DiskKey = 0;
  239.                     fib->fib_DirEntryType = fib->fib_EntryType = ST_FILE;
  240.                     fib->fib_Protection = 0;
  241.                     fib->fib_Comment[0] = '\0';
  242.                     fib->fib_Date.ds_Days = 0;
  243.                     fib->fib_Date.ds_Minute = 0;
  244.                     fib->fib_Date.ds_Tick = 0;
  245.  
  246.                     if(fl->fl_Volume != MKBADDR(curdoslist)) {
  247.                         /* The reference disk is currently not inserted. */
  248.                         err2 = ERROR_DEVICE_NOT_MOUNTED;
  249.                         break;
  250.                     }
  251.  
  252.                     if((special = fl->fl_Key & FLKEY_SPECIALMASK)) {
  253.                         /* Examine virtual files */
  254.                         static struct { STRPTR s; ULONG l; } tbl[3] = {
  255.                             { VIRTUAL_FILE_D64, D64_SIZE },
  256.                             { VIRTUAL_FILE_OPT, 0 }
  257.                         };
  258.                         int index = (special>>FLKEY_SPECIALSHIFT)-2;
  259.  
  260.                         switch(special) {
  261.                             case FLKEY_DOLLAR:
  262.                                 strcpy(&fib->fib_FileName[1], VIRTUAL_FILE_DOLLAR);
  263.                                 fib->fib_FileName[0] = strlen(VIRTUAL_FILE_DOLLAR);
  264.                                 fib->fib_Size = curvolumenode->dollarlen;
  265.                                 error = DOSTRUE;
  266.                                 break;
  267.  
  268.                             case FLKEY_D64: case FLKEY_OPT:
  269.                                 strcpy(&fib->fib_FileName[1], tbl[index].s);
  270.                                 fib->fib_FileName[0] = strlen(tbl[index].s);
  271.                                 fib->fib_Size = tbl[index].l;
  272.                                 error = DOSTRUE;
  273.                                 break;
  274.  
  275.                             case FLKEY_DISKINFO:
  276.                                 strcpy(&fib->fib_FileName[1], VIRTUAL_FILE_DISKINFO);
  277.                                 fib->fib_FileName[0] = strlen(VIRTUAL_FILE_DISKINFO);
  278.                                 fib->fib_Size = diskiconlength;
  279.                                 error = DOSTRUE;
  280.                                 break;
  281.  
  282.                             default:
  283.                                 err2 = ERROR_OBJECT_NOT_FOUND;
  284.                                 break;
  285.                         }
  286.                     }
  287.                     else {
  288.                         for(entry=0;entry<dirsize;entry++)
  289.                             if(fl->fl_Key == ((directory[entry].datat<<8)|directory[entry].datas))
  290.                                 break;
  291.     
  292.                         if(entry<dirsize) {
  293.                             if(getfiledata(entry, &fharg1)) {
  294.                                 copy64name(&fib->fib_FileName[1], directory[entry].name, 16);
  295.                                 fib->fib_FileName[0] = strlen(&fib->fib_FileName[1]);
  296.                                 fib->fib_Size = fharg1.len;
  297.                                 error = DOSTRUE;
  298.                             }
  299.                             else err2 = ERROR_OBJECT_NOT_FOUND;
  300.                         }
  301.                         else err2 = ERROR_OBJECT_NOT_FOUND;
  302.                     }
  303.                 }
  304.                 else {
  305.                     /* Prepare for EXAMINE_NEXT, return volume name in
  306.                        fib_FileName */
  307.                     fib->fib_DiskKey = 0;
  308.                     fib->fib_DirEntryType = fib->fib_EntryType = ST_ROOT;
  309.                     strcpy(&fib->fib_FileName[1], &curvolumenode->name[1]);
  310.                     fib->fib_FileName[0] = strlen(&fib->fib_FileName[1]);
  311.                     fib->fib_Protection = 0;
  312.                     fib->fib_Comment[0] = '\0';
  313.                     fib->fib_Date.ds_Days = 0;
  314.                     fib->fib_Date.ds_Minute = 0;
  315.                     fib->fib_Date.ds_Tick = 0;
  316.                     error = DOSTRUE;
  317.                 }
  318.  
  319.                 break;
  320.             }
  321.  
  322.             case ACTION_EXAMINE_NEXT:
  323.             {
  324.                 struct FileLock *fl = BADDR(packet->dp_Arg1);
  325.                 struct FileInfoBlock *fib = BADDR(packet->dp_Arg2);
  326.  
  327.                 if((err2 = TestLock(fl)))
  328.                     break;
  329.  
  330.                 fib->fib_DirEntryType = fib->fib_EntryType = ST_FILE;
  331.  
  332.                 err2 = ERROR_NO_MORE_ENTRIES;
  333.  
  334.                 while(fib->fib_DiskKey < dirsize) {
  335.                     int entry;
  336.                     struct FHArg1 fharg1;
  337.  
  338.                     entry = fib->fib_DiskKey++;
  339.  
  340.                     if(getfiledata(entry, &fharg1)) {
  341.                         copy64name(&fib->fib_FileName[1], directory[entry].name, 16);
  342.                         fib->fib_FileName[0] = strlen(&fib->fib_FileName[1]);
  343.                         fib->fib_Size = fharg1.len;
  344.                         fib->fib_NumBlocks = fharg1.numblocks;
  345.                         error = DOSTRUE;
  346.                         break;
  347.                     }
  348.                 }
  349.  
  350.                 if(error == DOSFALSE)
  351.                     MotorOff();
  352.  
  353.                 break;
  354.             }
  355.  
  356.             case ACTION_FINDINPUT:
  357.             case ACTION_FINDOUTPUT:
  358.             case ACTION_FINDUPDATE:
  359.             {
  360.                 struct FileHandle *fh = BADDR(packet->dp_Arg1);
  361.                 struct FileLock *fl = BADDR(packet->dp_Arg2);
  362.                 struct FHArg1 *fharg1;
  363.                 LONG access = packet->dp_Type==ACTION_FINDINPUT ? SHARED_LOCK : EXCLUSIVE_LOCK;
  364.  
  365.                 if((err2 = TestLock(fl)))
  366.                     break;
  367.  
  368.                 if((fharg1 = AllocVec(sizeof(struct FHArg1), MEMF_ANY|MEMF_CLEAR))) {
  369.                     if(trylockfile(&err2, packet->dp_Arg3, access, fharg1, FALSE)) {
  370.                         if(fharg1->number!=NUM_VIRTUAL || access==SHARED_LOCK
  371.                         || (((struct FileLock*)BADDR(fharg1->lock))->fl_Key & FLKEY_SPECIALMASK) == FLKEY_D64) {
  372.                             /* Allow virtual files only for reading, exception is $d64 */
  373.                             fh->fh_Arg1 = (LONG)fharg1;
  374.                             fh->fh_Port = DOSFALSE;
  375.                             error = DOSTRUE;
  376.                         }
  377.                         else {
  378.                             /* But new files with virtual file names can be created,
  379.                                 which will be real then. */
  380.                             freelock((struct FileLock*)BADDR(fharg1->lock));
  381.                             err2 = ERROR_OBJECT_NOT_FOUND;
  382.                         }
  383.                     }
  384.  
  385.                     if((error==DOSFALSE && access==EXCLUSIVE_LOCK && err2!=ERROR_INVALID_COMPONENT_NAME) || packet->dp_Type==ACTION_FINDOUTPUT) {
  386.                         if(!wprotected) {
  387.                             if(error==DOSFALSE) {
  388.                                 /* Create new file */
  389.                                 UWORD dblk;
  390.     
  391.                                 if(dirsize < 144) {
  392.                                     if((dblk = AllocBlock(17,0))) {
  393.                                         UBYTE clrblk[256];
  394.     
  395.                                         memset(&clrblk, 0, sizeof(clrblk));
  396.                                         clrblk[1] = 1;
  397.     
  398.                                         if(putblock_ts(dblk>>8, dblk&0xff, &clrblk)) {
  399.                                             struct DirEntry *de = &directory[dirsize++];
  400.     
  401.                                             memset(de, 0, sizeof(struct DirEntry));
  402.                                             de->type = 0x82; /* PRG, closed */
  403.                                             de->datat = dblk>>8;
  404.                                             de->datas = dblk&0xff;
  405.                                             de->lengthl = 1;
  406.                                             asciito64(de->name, fname1, 16);
  407.                                             StartUDSTimer();
  408.     
  409.                                             if(trylockfile(&err2, packet->dp_Arg3, access, fharg1, FALSE)) {
  410.                                                 fh->fh_Arg1 = (LONG)fharg1;
  411.                                                 fh->fh_Port = DOSFALSE;
  412.                                                 error = DOSTRUE;
  413.                                             }
  414.                                         }
  415.                                         else {
  416.                                             err2 = ABORT_DISK_ERROR;
  417.                                             FreeBlock(dblk>>8, dblk&0xff);
  418.                                         }
  419.                                     }
  420.                                     else err2 = ERROR_DISK_FULL;
  421.                                 }
  422.                                 else err2 = ERROR_DISK_FULL;
  423.                             }
  424.                             else if(fharg1->number != NUM_VIRTUAL) /* trying to overwrite $d64 */ {
  425.                                 /* Overwrite existing file */
  426.                                 struct DataBlock *block;
  427.                                 UBYTE t,s;
  428.                                 int i;
  429.     
  430.                                 for(i=0,t=fharg1->t,s=fharg1->s; t; t=block->t,s=block->s,i++) {
  431.                                     block = getblock_ts(t,s);
  432.                                     if(i>0) FreeBlock(t,s);
  433.                                 }
  434.                                 fharg1->len = 0;
  435.                                 fharg1->numblocks = 1;
  436.                                 block = getblock_ts(fharg1->t, fharg1->s);
  437.                                 block->t = 0;
  438.                                 block->s = 1;
  439.                                 putblock_ts(fharg1->t, fharg1->s, block);
  440.                             }
  441.                         }
  442.                         else err2 = ERROR_DISK_WRITE_PROTECTED;
  443.                     }
  444.                     else {
  445.                         if(error==DOSTRUE) {
  446.                             /* Open existing file, already done. */
  447.                         }
  448.                         /* else err2 still set from first trylockfile() call */
  449.                     }
  450.  
  451.                     if(error == DOSFALSE) {
  452.                         FreeVec(fharg1);
  453.                         MotorOff();
  454.                     }
  455.                 }
  456.                 else err2 = ERROR_NO_FREE_STORE;
  457.  
  458.                 break;
  459.             }
  460.  
  461.             case ACTION_READ:
  462.             {
  463.                 struct FHArg1 *fharg1 = (struct FHArg1 *)packet->dp_Arg1;
  464.                 APTR buffer = (APTR)packet->dp_Arg2;
  465.                 ULONG togo = packet->dp_Arg3;
  466.                 struct DataBlock *block = NULL;
  467.  
  468.                 if((err2 = TestLockRef((struct FileLock*)BADDR(fharg1->lock)))) {
  469.                     error = -1;
  470.                     break;
  471.                 }
  472.  
  473.                 if(fharg1->pos + togo >= fharg1->len)
  474.                     togo = fharg1->len - fharg1->pos;
  475.  
  476.                 error = 0;
  477.  
  478.                 if(fharg1->number == NUM_VIRTUAL) {
  479.                     /* Handle virtual files */
  480.                     int special = ((struct FileLock*)BADDR(fharg1->lock))->fl_Key & FLKEY_SPECIALMASK;
  481.  
  482.                     switch(special) {
  483.                         case FLKEY_DOLLAR:
  484.                             CopyMem(&curvolumenode->dollarbuf[fharg1->pos], buffer, togo);
  485.                             fharg1->pos += togo;
  486.                             error += togo;
  487.                             break;
  488.  
  489.                         case FLKEY_DISKINFO:
  490.                             CopyMem(&diskiconimg[fharg1->pos], buffer, togo);
  491.                             fharg1->pos += togo;
  492.                             error += togo;
  493.                             break;
  494.  
  495.                         case FLKEY_D64:
  496.                             while(togo) {
  497.                                 ULONG size, offset;
  498.  
  499.                                 if(!(block = getputblock((fharg1->pos)>>8, FALSE)))
  500.                                     break;
  501.  
  502.                                 offset = (fharg1->pos) & 255;
  503.  
  504.                                 size = 256 - offset;
  505.                                 if(togo < size)
  506.                                     size = togo;
  507.  
  508.                                 CopyMem(&((UBYTE*)block)[offset], buffer, size);
  509.  
  510.                                 buffer += size;
  511.                                 fharg1->pos += size;
  512.                                 error += size;
  513.                                 togo -= size;
  514.                             }
  515.                             break;
  516.  
  517.                         default:
  518.                             break;
  519.                     }
  520.                 }
  521.                 else {
  522.                     /* Handle real files */
  523.                     while(togo) {
  524.                         ULONG size;
  525.     
  526.                         if(fharg1->p == 254) {
  527.                             if(!block)
  528.                                 if(!(block = getblock_ts(fharg1->t, fharg1->s)))
  529.                                     break;
  530.                             fharg1->p = 0;
  531.                             fharg1->t = block->t;
  532.                             fharg1->s = block->s;
  533.                         }
  534.     
  535.                         size = 254 - fharg1->p;
  536.                         if(togo < size)
  537.                             size = togo;
  538.     
  539.                         if(!(block = getblock_ts(fharg1->t, fharg1->s)))
  540.                             break;
  541.     
  542.                         CopyMem(&block->data[fharg1->p], buffer, size);
  543.                         buffer += size;
  544.                         fharg1->p += size;
  545.                         fharg1->pos += size;
  546.                         error += size;
  547.                         togo -= size;
  548.                     }
  549.                 }
  550.  
  551.                 break;
  552.             }
  553.  
  554.             case ACTION_WRITE:
  555.             {
  556.                 struct FHArg1 *fharg1 = (struct FHArg1 *)packet->dp_Arg1;
  557.                 APTR buffer = (APTR)packet->dp_Arg2;
  558.                 ULONG togo = packet->dp_Arg3;
  559.                 struct DataBlock *block = NULL;
  560.                 struct DataBlock newblk;
  561.  
  562.                 error = -1;
  563.  
  564.                 if((err2 = TestLockRef((struct FileLock*)BADDR(fharg1->lock))))
  565.                     break;
  566.  
  567.                 if(wprotected) {
  568.                     err2 = ERROR_DISK_WRITE_PROTECTED;
  569.                     break;
  570.                 }
  571.  
  572.                 error = 0;
  573.  
  574.                 if((((struct FileLock*)BADDR(fharg1->lock))->fl_Key & FLKEY_SPECIALMASK) == FLKEY_D64) {
  575.                     /* Handle writes to the $d64 file */
  576.                     if(fharg1->pos + togo > D64_SIZE)
  577.                         togo = D64_SIZE - fharg1->pos;
  578.  
  579.                     while(togo) {
  580.                         ULONG size, offset;
  581.  
  582.                         if(!(block = getputblock((fharg1->pos)>>8, FALSE)))
  583.                             break;
  584.  
  585.                         offset = (fharg1->pos) & 255;
  586.  
  587.                         size = 256 - offset;
  588.                         if(togo < size)
  589.                             size = togo;
  590.  
  591.                         CopyMem(buffer, &((UBYTE*)block)[offset], size);
  592.                         getputblock((fharg1->pos)>>8, TRUE);
  593.  
  594.                         buffer += size;
  595.                         fharg1->pos += size;
  596.                         error += size;
  597.                         togo -= size;
  598.                     }
  599.                     break;
  600.                 }
  601.  
  602.                 while(togo) {
  603.                     ULONG size;
  604.  
  605.                     if(!block)
  606.                         block = getblock_ts(fharg1->t, fharg1->s);
  607.  
  608.                     if(fharg1->p == 254) {
  609.                         /* Switch to next block */
  610.                         if(!block->t) {
  611.                             /* Allocate new block */
  612.                             UWORD dblk;
  613.  
  614.                             if(!(dblk = AllocBlock(fharg1->t, fharg1->s))) {
  615.                                 err2 = ERROR_DISK_FULL;
  616.                                 break;
  617.                             }
  618.  
  619.                             fharg1->p = 0;
  620.                             block->t = dblk>>8;
  621.                             block->s = dblk&0xff;
  622.                             putblock_ts(fharg1->t, fharg1->s, block); /* link to previous block */
  623.                             fharg1->t = block->t;
  624.                             fharg1->s = block->s;
  625.                             fharg1->numblocks++;
  626.  
  627.                             block = &newblk;
  628.                             memset(&newblk, 0, sizeof(newblk));
  629.                             block->t = 0;
  630.                             block->s = 1;
  631.                         }
  632.                         else {
  633.                             /* Jump to existing next block */
  634.                             fharg1->p = 0;
  635.                             fharg1->t = block->t;
  636.                             fharg1->s = block->s;
  637.                             block = getblock_ts(fharg1->t, fharg1->s);
  638.                         }
  639.                     }
  640.  
  641.                     size = 254 - fharg1->p;
  642.                     if(togo < size)
  643.                         size = togo;
  644.  
  645.                     /* Insert data */
  646.                     CopyMem(buffer, &block->data[fharg1->p], size);
  647.                     buffer += size;
  648.  
  649.                     /* Advance block pointer and dump it */
  650.                     fharg1->p += size;
  651.                     if(!block->t)
  652.                         block->s = fharg1->p + 1;
  653.                     putblock_ts(fharg1->t, fharg1->s, block);
  654.  
  655.                     /* Adjust length field if necessary */
  656.                     fharg1->pos += size;
  657.                     if(fharg1->pos > fharg1->len)
  658.                         fharg1->len = fharg1->pos;
  659.  
  660.                     error += size;
  661.                     togo -= size;
  662.                 }
  663.  
  664.                 break;
  665.             }
  666.  
  667.             case ACTION_SET_FILE_SIZE: {
  668.                 error = -1;
  669.                 err2 = ERROR_ACTION_NOT_KNOWN;
  670.                 break;
  671.             }
  672.  
  673.             case ACTION_SEEK:
  674.             {
  675.                 struct FHArg1 fharg1bak, *fharg1 = (struct FHArg1 *)packet->dp_Arg1;
  676.                 LONG move = packet->dp_Arg2;
  677.  
  678.                 if((err2 = TestLockRef((struct FileLock*)BADDR(fharg1->lock))))
  679.                     break;
  680.  
  681.                 error = fharg1->pos;
  682.                 err2 = ERROR_SEEK_ERROR;
  683.  
  684.                 switch(packet->dp_Arg3) {
  685.                     case OFFSET_BEGINNING:
  686.                         move = move - error;
  687.                         break;
  688.  
  689.                     case OFFSET_CURRENT:
  690.                         break;
  691.  
  692.                     case OFFSET_END:
  693.                         move = move + fharg1->len - error;
  694.                         break;
  695.  
  696.                     default:
  697.                         error = -1;
  698.                         break;
  699.                 }
  700.  
  701.                 if(error != -1) {
  702.                     CopyMem(fharg1, &fharg1bak, sizeof(struct FHArg1));
  703.  
  704.                     if((error+move)<0 || (error+move)>fharg1->len)
  705.                         error = -1;
  706.                     else {
  707.                         if(((struct FileLock*)BADDR(fharg1->lock))->fl_Key & FLKEY_SPECIALMASK) {
  708.                             /* Virtual files are easy */
  709.                             fharg1->pos += move;
  710.                         }
  711.                         else {
  712.                             if(move<0) {
  713.                                 /* When moving back, we have to rescan the whole file */
  714.                                 move = move + error;
  715.                                 fharg1->p = 0;
  716.                                 fharg1->pos = 0;
  717.                                 fharg1->t = fharg1->t0;
  718.                                 fharg1->s = fharg1->s0;
  719.                             }
  720.     
  721.                             while(move) {
  722.                                 ULONG size;
  723.                                 struct DataBlock *block;
  724.     
  725.                                 if(fharg1->p == 254) {
  726.                                     block = getblock_ts(fharg1->t, fharg1->s);
  727.  
  728.                                     if(!block) {
  729.                                         CopyMem(&fharg1bak, fharg1, sizeof(struct FHArg1));
  730.                                         error = -1;
  731.                                         err2 = ABORT_DISK_ERROR;
  732.                                         break;
  733.                                     }
  734.  
  735.                                     fharg1->p = 0;
  736.                                     fharg1->t = block->t;
  737.                                     fharg1->s = block->s;
  738.                                 }
  739.     
  740.                                 size = 254 - fharg1->p;
  741.             
  742.                                 if(move < size)
  743.                                     size = move;
  744.             
  745.                                 fharg1->p += size;
  746.                                 fharg1->pos += size;
  747.                                 move -= size;
  748.                             }
  749.                         }
  750.                     }
  751.                 }
  752.  
  753.                 break;
  754.             }
  755.  
  756.             case ACTION_END:
  757.             {
  758.                 struct FHArg1 *fharg1 = (struct FHArg1 *)packet->dp_Arg1;
  759.  
  760.                 if((err2 = TestLockRef((struct FileLock*)BADDR(fharg1->lock))))
  761.                     break;
  762.  
  763.                 if(fharg1->len != fharg1->len0) {
  764.                     /* File has been modified, update disk structure */
  765.                     int i;
  766.  
  767.                     for(i=0; i<dirsize; i++) {
  768.                         if(directory[i].datat == fharg1->t0
  769.                            && directory[i].datas == fharg1->s0) {
  770.                             UWORD blks = fharg1->numblocks;
  771.                             directory[i].lengthl = blks & 0xff;
  772.                             directory[i].lengthh = blks >> 8;
  773.                             directory[i].type |= 0x80; // mark file as closed
  774.                             break;
  775.                         }
  776.                     }
  777.  
  778.                     StartUDSTimer();
  779.                 }
  780.  
  781.                 freelock(BADDR(fharg1->lock));
  782.                 FreeVec(fharg1);
  783.  
  784.                 error = DOSTRUE;
  785.                 break;
  786.             }
  787.  
  788.             case ACTION_IS_FILESYSTEM:
  789.                 /* Yes, we are. */
  790.                 error = DOSTRUE;
  791.                 break;
  792.  
  793.             case ACTION_CURRENT_VOLUME:
  794.             {
  795.                 struct FHArg1 *fharg1 = (struct FHArg1 *)packet->dp_Arg1;
  796.  
  797.                 /* The packet name is somewhat misleading... */
  798.                 if(fharg1)
  799.                     error = ((struct FileLock*)BADDR(fharg1->lock))->fl_Volume;
  800.                 else {
  801.                     if(curvolumenode)
  802.                         error = (LONG)MKBADDR(curdoslist);
  803.                     else
  804.                         error = NULL;
  805.                 }
  806.  
  807.                 break;
  808.             }
  809.  
  810.             case ACTION_INFO:
  811.             case ACTION_DISK_INFO:
  812.             {
  813.                 struct InfoData *id;
  814.  
  815.                 if(packet->dp_Type == ACTION_INFO) {
  816.                     struct FileLock *fl = BADDR(packet->dp_Arg1);
  817.  
  818.                     if(fl && fl->fl_Volume != MKBADDR(curdoslist)) {
  819.                         /* The reference disk is currently not inserted. */
  820.                         err2 = ERROR_DEVICE_NOT_MOUNTED;
  821.                         break;
  822.                     }
  823.  
  824.                     id = BADDR(packet->dp_Arg2);
  825.                 }
  826.                 else {
  827.                     id = BADDR(packet->dp_Arg1);
  828.                 }
  829.  
  830.                 id->id_NumSoftErrors = numsofterrors;
  831.                 id->id_NumBlocks = 683;
  832.                 id->id_NumBlocksUsed = UsedBlocks();
  833.                 id->id_BytesPerBlock = 254;
  834.                 id->id_DiskState = hardwprot ? ID_WRITE_PROTECTED : (wprotected ? ID_VALIDATING : ID_VALIDATED);
  835.                 id->id_UnitNumber = fssm->fssm_Unit;
  836.  
  837.                 if(curvolumenode) {
  838.                     id->id_DiskType = ID_DOS_DISK;
  839.                     id->id_VolumeNode = MKBADDR(curdoslist);
  840.                     id->id_InUse = curvolumenode->locklist ? DOSTRUE : DOSFALSE;
  841.                 }
  842.                 else {
  843.                     #ifndef ID_BUSY /* My v40 header files don't */
  844.                     #define ID_BUSY 0x42555359
  845.                     #endif
  846.                     id->id_DiskType = inhibited ? ID_BUSY : (disk_inserted ? ID_UNREADABLE_DISK : ID_NO_DISK_PRESENT);
  847.                 }
  848.  
  849.                 error = DOSTRUE;
  850.  
  851.                 break;
  852.             }
  853.  
  854.             case ACTION_INHIBIT:
  855.             {
  856.                 /* We could have trouble here if the DosList is locked,
  857.                    but then again, one shouldn't lock it for INHIBIT. */
  858.  
  859.                 if(packet->dp_Arg1 == DOSTRUE) {
  860.                     if(inhibited == FALSE) {
  861.                         inhibited = TRUE;
  862.  
  863.                         StopUDSTimer();
  864.                         MotorOff();
  865.                         DoDiskRemove();
  866.                     }
  867.                 }
  868.                 else if(inhibited == TRUE) {
  869.                     DoDiskInsert();
  870.  
  871.                     inhibited = FALSE;
  872.                 }
  873.  
  874.                 error = DOSTRUE;
  875.  
  876.                 break;
  877.             }
  878.  
  879.             case ACTION_CREATE_DIR:
  880.                 err2 = ERROR_INVALID_COMPONENT_NAME;
  881.                 break;
  882.  
  883.             case ACTION_DELETE_OBJECT:
  884.             {
  885.                 struct FileLock *fl = BADDR(packet->dp_Arg1);
  886.                 struct FHArg1 fharg1;
  887.  
  888.                 if((err2 = TestLock(fl)))
  889.                     break;
  890.  
  891.                 if(!wprotected) {
  892.                     if(trylockfile(&err2, packet->dp_Arg2, EXCLUSIVE_LOCK, &fharg1, FALSE)) {
  893.                         struct DataBlock *block;
  894.                         UBYTE t,s;
  895.     
  896.                         freelock((struct FileLock*)BADDR(fharg1.lock));
  897.     
  898.                         if(fharg1.number != NUM_VIRTUAL) {
  899.                             /* We do this only for non-virtual files. */
  900.                             for(t=fharg1.t,s=fharg1.s; t; t=block->t,s=block->s) {
  901.                                 block = getblock_ts(t,s);
  902.                                 FreeBlock(t,s);
  903.                             }
  904.         
  905.                             directory[fharg1.number].type = 0x00;
  906.                             StartUDSTimer();
  907.                             error = DOSTRUE;
  908.                         }
  909.                         else err2 = ERROR_DELETE_PROTECTED;
  910.                     }
  911.                 }
  912.                 else err2 = ERROR_DISK_WRITE_PROTECTED;
  913.  
  914.                 MotorOff();
  915.                 break;
  916.             }
  917.  
  918.             case ACTION_FORMAT:
  919.             {
  920.                 UBYTE buf[18];
  921.                 STRPTR a;
  922.                 struct DataBlock blk1;
  923.  
  924.                 if(!inhibited) {
  925.                     /* Amiga Guru Book p. 431, 17.1.50 Format():
  926.                        "Before a medium can be high-level formatted, the
  927.                        associated DOS device must have been inhibited..." */
  928.                     err2 = ERROR_OBJECT_IN_USE;
  929.                     break;
  930.                 }
  931.  
  932.                 ResetDisk();
  933.  
  934.                 if(!hardwprot) {
  935.                     if((a = BADDR(packet->dp_Arg1))) {
  936.                         int l = a[0]>16 ? 16 : a[0];
  937.                         CopyMem(&a[1], buf, l);
  938.                         buf[l] = '\0';
  939.                     }
  940.                     else buf[0] = '\0';
  941.  
  942.                     asciito64(empty_bam.name, buf, 16);
  943.                 /*    empty_bam[0].name2=(rand()&0x3F)+32;
  944.                     empty_bam[1].name2=(rand()&0x3F)+32; */
  945.                     putblock_ts(18,0,&empty_bam);
  946.                     memset(&blk1, 0, sizeof(blk1));
  947.                     blk1.s = 0xff;
  948.                     putblock_ts(18,1,&blk1);
  949.  
  950.                     error = DOSTRUE;
  951.                 }
  952.                 else err2 = ERROR_DISK_WRITE_PROTECTED;
  953.  
  954.                 /* we don't have to DoDiskInsert() here --
  955.                    it's done in the final ACTION_INHIBIT. */
  956.                 break;
  957.             }
  958.  
  959.             case ACTION_RENAME_DISK:
  960.             {
  961.                 UBYTE buf[18];
  962.                 STRPTR a;
  963.  
  964.                 if(curvolumenode) {
  965.                     if(!wprotected) {
  966.                         if((a = BADDR(packet->dp_Arg1))) {
  967.                             int l = a[0]>16 ? 16 : a[0];
  968.                             CopyMem(&a[1], buf, l);
  969.                             buf[l] = '\0';
  970.                         }
  971.                         else buf[0] = '\0';
  972.  
  973.                         asciito64(bam->name, buf, 16);
  974.  
  975.                         while(!AttemptLockDosList(LDF_VOLUMES|LDF_WRITE))
  976.                             DoPackets();
  977.                         copy64name(&curvolumenode->name[1], bam->name, 16);
  978.                         curvolumenode->name[0] = strlen(&curvolumenode->name[1]);
  979.                         UnLockDosList(LDF_VOLUMES|LDF_WRITE);
  980.  
  981.                         StartUDSTimer();
  982.  
  983.                         error = DOSTRUE;
  984.                     }
  985.                     else err2 = ERROR_DISK_WRITE_PROTECTED;
  986.                 }
  987.                 else err2 = disk_inserted ? ERROR_NOT_A_DOS_DISK : ERROR_NO_DISK;
  988.  
  989.                 break;
  990.             }
  991.  
  992.             case ACTION_RENAME_OBJECT:
  993.             {
  994.                 struct FileLock *fl1 = BADDR(packet->dp_Arg1),
  995.                                 *fl2 = BADDR(packet->dp_Arg3);
  996.                 struct FHArg1 fharg1;
  997.  
  998.                 if(!((err2 = TestLock(fl1)) || (err2 = TestLock(fl2)))) {
  999.                     if(!wprotected) {
  1000.                         if(trylockfile(&err2, packet->dp_Arg2, SHARED_LOCK, &fharg1, FALSE)) {
  1001.                             freelock((struct FileLock*)BADDR(fharg1.lock));
  1002.  
  1003.                             if(fharg1.number != NUM_VIRTUAL) {
  1004.                                 STRPTR a;
  1005.                                 UBYTE buf[256];
  1006.  
  1007.                                 if((a = BADDR(packet->dp_Arg4))) {
  1008.                                     CopyMem(&a[1], buf, a[0]);
  1009.                                     buf[a[0]] = '\0';
  1010.  
  1011.                                     if(!strchr(buf, '/')) {
  1012.                                         a = strchr(buf, ':');
  1013.                                         strncpy(fname1, a ? a+1 : buf, 17);
  1014.                                         fname1[16] = '\0';
  1015.  
  1016.                                         asciito64(directory[fharg1.number].name, fname1, 16);
  1017.                                         StartUDSTimer();
  1018.                                         error = DOSTRUE;
  1019.                                     }
  1020.                                     else err2 = ERROR_INVALID_COMPONENT_NAME;
  1021.                                 }
  1022.                                 else err2 = ERROR_INVALID_COMPONENT_NAME;
  1023.                             }
  1024.                             else err2 = ERROR_OBJECT_NOT_FOUND;
  1025.                         }
  1026.                     }
  1027.                     else err2 = ERROR_DISK_WRITE_PROTECTED;
  1028.                 }
  1029.  
  1030.                 break;
  1031.             }
  1032.  
  1033.             default:
  1034.                 err2 = ERROR_ACTION_NOT_KNOWN;
  1035.                 break;
  1036.         }
  1037.     
  1038.         ReturnPacket(packet, error, err2);
  1039.     }
  1040. }
  1041.  
  1042. static LONG TestLock(struct FileLock *fl)
  1043. {
  1044.     if(fl) {
  1045.         if(fl->fl_Volume != MKBADDR(curdoslist))
  1046.             /* The reference disk is currently not inserted. */
  1047.             return(ERROR_DEVICE_NOT_MOUNTED);
  1048.         if(fl->fl_Key != 0)
  1049.             /* An invalid lock has been passed. */
  1050.             return(ERROR_OBJECT_WRONG_TYPE);
  1051.     }
  1052.     return(0);
  1053. }
  1054.  
  1055. static inline LONG TestLockRef(struct FileLock *fl)
  1056. {
  1057.     if(fl->fl_Volume != MKBADDR(curdoslist))
  1058.         /* The reference disk is currently not inserted. */
  1059.         return(ERROR_DEVICE_NOT_MOUNTED);
  1060.     return(0);
  1061. }
  1062.  
  1063. /*-------------------------------------------------------------------------*/
  1064.  
  1065. static BOOL getfiledata(UBYTE entry, struct FHArg1 *fharg1)
  1066. {
  1067.     if(directory[entry].name[0] != 0xa0) {
  1068.         UWORD type = (directory[entry].type) & 0x7;
  1069.  
  1070.         if(type!=0x00) { // anything but DEL-Files
  1071.             struct DataBlock *block;
  1072.             int i,t,s,size;
  1073.  
  1074.             for(i=0,t=directory[entry].datat,s=directory[entry].datas,size=0;
  1075.                 i<683; /* a primitive solution to overcome circular links */
  1076.                 t=block->t,s=block->s,i++)
  1077.             {
  1078.                 if(!(block = getblock_ts(t,s)))
  1079.                     return(FALSE);
  1080.  
  1081.                 if(block->t)
  1082.                     size+=254;
  1083.                 else {
  1084.                     size+=block->s-1;
  1085.                     break;
  1086.                 }
  1087.             }
  1088.  
  1089.             if(i<683) {
  1090.                 fharg1->len = fharg1->len0 = size;
  1091.                 fharg1->numblocks = i+1;
  1092.                 fharg1->t = fharg1->t0 = directory[entry].datat;
  1093.                 fharg1->s = fharg1->s0 = directory[entry].datas;
  1094.                 fharg1->number = entry;
  1095.                 return(TRUE);
  1096.             }
  1097.         }
  1098.     }
  1099.  
  1100.     return(FALSE);
  1101. }
  1102.  
  1103. /*-------------------------------------------------------------------------*/
  1104.  
  1105. /* May only be called if curvolumenode is valid! */
  1106. static BPTR trylockfile(LONG *err2, BSTR name, LONG access, struct FHArg1 *fharg1, BOOL allow_root)
  1107. {
  1108.     UBYTE buf[256];
  1109.     STRPTR a;
  1110.     LONG error;
  1111.  
  1112.     error = DOSFALSE;
  1113.  
  1114.     /* Convert BSTR argument into C string */
  1115.     if((a = BADDR(name))) {
  1116.         CopyMem(&a[1], buf, a[0]);
  1117.         buf[a[0]] = '\0';
  1118.  
  1119.         if(strchr(buf, '/')) {
  1120.             /* User tries to access subdirectories */
  1121.             *err2 = ERROR_INVALID_COMPONENT_NAME;
  1122.             return(error);
  1123.         }
  1124.  
  1125.         a = strchr(buf, ':');
  1126.         strncpy(fname1, a ? a+1 : buf, 17);
  1127.         fname1[16] = '\0';
  1128.     }
  1129.     else
  1130.         fname1[0] = '\0';
  1131.  
  1132.     if(fname1[0] == '\0') {
  1133.         if(allow_root) {
  1134.             /* Return lock on root directory */
  1135.             if(access == EXCLUSIVE_LOCK) {
  1136.                 *err2 = ERROR_OBJECT_IN_USE;
  1137.             }
  1138.             else {
  1139.                 *err2 = ERROR_NO_FREE_STORE;
  1140.                 error = makelock(0, access);
  1141.             }
  1142.         }
  1143.         else *err2 = ERROR_OBJECT_WRONG_TYPE;
  1144.     }
  1145.     else {
  1146.         int entry;
  1147.  
  1148.         *err2 = ERROR_OBJECT_NOT_FOUND;
  1149.  
  1150.         /* Look up file in directory and lock it */
  1151.         for(entry=0;entry<dirsize;entry++) {
  1152.             copy64name(buf, directory[entry].name, 16);
  1153.             if(!Stricmp(buf, fname1))
  1154.                 break;
  1155.         }
  1156.  
  1157.         if(entry == dirsize) {
  1158.             /* Perhaps we can provide a virtual file */
  1159.             fharg1->number = NUM_VIRTUAL;
  1160.  
  1161.             if(!Stricmp(VIRTUAL_FILE_DISKINFO,fname1)) {
  1162.                 *err2 = ERROR_NO_FREE_STORE;
  1163.                 error = fharg1->lock = makelock(FLKEY_DISKINFO, access);
  1164.                 fharg1->len = fharg1->len0 = diskiconlength;
  1165.             }
  1166.             else if(fname1[0] == '$') {
  1167.                 if(!Stricmp(VIRTUAL_FILE_DOLLAR,fname1)) {
  1168.                     *err2 = ERROR_NO_FREE_STORE;
  1169.                     error = fharg1->lock = makelock(FLKEY_DOLLAR, access);
  1170.                     fharg1->len = fharg1->len0 = curvolumenode->dollarlen;
  1171.                 }
  1172.                 else if(!Stricmp(VIRTUAL_FILE_D64,fname1)) {
  1173.                     *err2 = ERROR_NO_FREE_STORE;
  1174.                     error = fharg1->lock = makelock(FLKEY_D64, access);
  1175.                     fharg1->len = fharg1->len0 = D64_SIZE;
  1176.                 }
  1177.                 else if(!Stricmp(VIRTUAL_FILE_OPT,fname1)) {
  1178.                     if(!wprotected) {
  1179.                         *err2 = ERROR_NO_FREE_STORE;
  1180.                         error = fharg1->lock = makelock(FLKEY_OPT, access);
  1181.                         fharg1->len = fharg1->len0 = 0;
  1182.                         OptimizeDirectory();
  1183.                         StartUDSTimer();
  1184.                     }
  1185.                     else *err2 = ERROR_DISK_WRITE_PROTECTED;
  1186.                 }
  1187.             }
  1188.         }
  1189.         else {
  1190.             if(getfiledata(entry, fharg1)) {
  1191.                 if(lockable(fharg1->t, fharg1->s, access)) {
  1192.                     *err2 = ERROR_NO_FREE_STORE;
  1193.                     error = fharg1->lock = makelock(((fharg1->t)<<8)|fharg1->s, access);
  1194.                 }
  1195.                 else *err2 = ERROR_OBJECT_IN_USE;
  1196.             }
  1197.         }
  1198.     }
  1199.  
  1200.     return(error);
  1201. }
  1202.  
  1203. /*
  1204.   Local Variables:
  1205.   mode:c
  1206.   c-basic-offset:8
  1207.   End:
  1208. */
  1209.